/* 
 * File:   Conexion.cpp
 * Author: max
 * 
 * Created on October 18, 2012, 7:00 PM
 */

#include <iostream>
#include "errno.h"
#include "server_Conexion.h"
#include "server_SockEndPoint.h"
#include "common_MutexScopeLocker.h"

using namespace std;
using namespace TP;
using namespace TP::Comunicacion;

#define PERDIDA_CONEXION 0
#define ERROR_CONEXION -1

Conexion::Conexion(const string& pPuerto, IManejadorConexionEvento* pManejador){
    
    _puerto = pPuerto;
    _socket = new SockStreamAsincronico();
    this->manejadorConexionEvento = pManejador;
    _permitirNuevasConexiones = false;
}

Conexion::~Conexion() {
    delete _socket;
}

void Conexion::Iniciar() throw (Excepcion&){
    
    try
    {
        if (NULL == this->manejadorConexionEvento)
        {
            throw Excepcion ("No hay definido un manejador de evento de nueva sesion.");
        }
        
        _socket->Iniciar();
        _socket->Bind(_puerto, INADDR_ANY);
        _socket->Listen(5);
        
        this->SetPermitirNuevasConexiones(true);
        
        // Inicio la ejecucion.
        Thread::Iniciar();
    }
    catch (Excepcion& pEx)
    {
        string msg = "No se puede inicar la conexion (Puerto: ";
        msg += _puerto;
        msg += ").";
        
        pEx.expandirMensaje(msg);
        throw;
    }
}

void Conexion::Finalizar() throw (Excepcion&){
    try
    {
        // Finalizo el socket de conexion.
        this->SetPermitirNuevasConexiones(false);
        _socket->Finalizar();
        
        Thread::Finalizar();
    }
    catch (Excepcion& pEx)
    {
        string msg = "No se puede finalizar la conexion (Puerto: " + _puerto + ").";
        
        pEx.expandirMensaje(msg);
        throw;
    }
}

void Conexion::tarea (){
    
    try
    {
        while (this->GetPermitirNuevasConexiones())
        {
            
            /* Para todo nuevo SockEndPoint creado desde el socket (conexion entrante)
             * se instancia una secion y se la delega al manejador de de eventos.
             */
            SockEndPointAsincronico* endPoint = _socket->Acept();
            Sesion* sesion = new Sesion(endPoint);
            
            this->manejadorConexionEvento->eventoNuevaSesion(reinterpret_cast <IEnviante*>(this), sesion);  
        }
    }
    catch (Excepcion &ex){
            
        if (this->GetPermitirNuevasConexiones())
        {
            this->Finalizar();
            this->manejadorConexionEvento->eventoErrorConexionInexistente(reinterpret_cast<IEnviante*>(this), ex.what());
            this->conexionFinalizada = true;
        }
    }
}

bool Conexion::GetPermitirNuevasConexiones (){
    MutexScopeLocker locker (_permitirNuevasConexionesMutex);
    return _permitirNuevasConexiones;
}

bool Conexion::SetPermitirNuevasConexiones (bool pValor){
    MutexScopeLocker locker (_permitirNuevasConexionesMutex);
    _permitirNuevasConexiones = pValor;
    return _permitirNuevasConexiones;
}